home *** CD-ROM | disk | FTP | other *** search
- /* TERM server: access a local asy device from a tcp connection.
- * Copyright 1991 Phil Karn, KA9Q
- * Adapted from KA9Q's NOS 930622 by N5KNX 11/95.
- */
- #include "global.h"
- #ifdef TERMSERVER
- #include "commands.h"
- #include "netuser.h"
- #include "smtp.h"
- #include "iface.h"
- #include "hardware.h"
- #include "mailbox.h"
- #include "asy.h"
- #ifdef UNIX
- #include "unixasy.h"
- #else
- #include "n8250.h"
- #endif
- #include "devparam.h"
- #ifndef MSDOS
- #include "telnet.h"
- #endif
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: term.c,v 1.12 1997/05/24 13:11:12 root Exp root $";
- #endif
-
- static void termserv (int s,void *unused,void *p);
- static void termrx (int s,void *p1,void *p2);
- static int prompting_read (const char *prompt, int s, char *buf, int buflen);
-
- static const char termlistener[] = "TERM listener";
- static const char termserver[] = "TERM server";
- static int S_term = -1;
-
- static char *Termpass = NULLCHAR;
- struct portlist {
- char *portname;
- struct portlist *next;
- };
- #define NULLPL (struct portlist *)NULL
- static struct portlist *Termports = NULLPL;
-
-
- /* Start up TCP term server */
- int
- term1 (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- int port = IPPORT_TERM;
-
- if (argc > 1) {
- port = atoi (argv[1]);
- tprintf ("Starting Term Server on port %d\n", port);
- }
- return (installserver (argc, argv, &S_term, termlistener, port,
- INADDR_ANY, termserver, termserv, 512, NULL));
- }
-
-
- /* Stop term server */
- int
- term0 (argc, argv, p)
- int argc OPTIONAL;
- char *argv[] OPTIONAL;
- void *p OPTIONAL;
- {
- return (deleteserver (&S_term));
- }
-
-
- static void
- termserv(s,unused,p)
- int s;
- void *unused OPTIONAL;
- void *p OPTIONAL;
- {
- char buf[64];
- struct iface *ifp = NULLIF;
- struct route *rp;
- struct sockaddr_in fsocket;
- struct proc *rxproc = NULLPROC;
- struct asy *ap = (struct asy *) 0;
- struct mbuf *bp;
- struct portlist *pl;
- int (*rawsave) (struct iface *,struct mbuf *) = NULLFP((struct iface*,struct mbuf*));
- int i, saved = 0;
-
- (void) sockmode (s, SOCK_BINARY);
- (void) sockowner (s, Curproc);
- close_s (Curproc->output);
- close_s (Curproc->input);
- Curproc->output = Curproc->input = s;
- (void) setflush (s, '\n');
- log (s, "open term");
-
- /* Prompt for and check remote password */
- if (Termpass) {
- if (prompting_read ("Password: ", s, buf, sizeof(buf)) < 0)
- goto quit;
- rip (buf);
- if (strcmp (buf, Termpass) != 0) {
- tputs ("Login incorrect\n");
- goto quit;
- }
- }
-
- /* Prompt for desired interface. Verify that it exists, that
- * we're not using it for our TCP connection, that it's an
- * asynch port, and that there isn't already another tip, term
- * or dialer session active on it.
- */
- for ( ; ; ) {
- if (prompting_read ("Interface: ", s, buf, sizeof(buf)) < 0)
- goto quit;
- rip (buf);
- if ((ifp = if_lookup (buf)) == NULLIF) {
- tprintf (Badinterface, buf);
- continue;
- }
- for (pl = Termports; pl; pl = pl->next)
- if (!strcmp (pl->portname, buf))
- break;
- if (!pl) {
- tprintf (Badinterface, buf);
- continue;
- }
- if (getpeername(s,(char *)&fsocket,&i) != -1
- && !ismyaddr(fsocket.sin_addr.s_addr)
- && (rp = rt_lookup(fsocket.sin_addr.s_addr)) != NULLROUTE
- && rp->iface == ifp) {
- tprintf ("You're using interface %s!\n", ifp->name);
- continue;
- }
-
- ap = &Asy[ifp->dev];
- if (ifp->dev >= ASY_MAX || ap->iface != ifp ) {
- tprintf ("Interface %s not asy port\n", buf);
- continue;
- }
- if (ifp->raw == bitbucket) {
- tprintf("%s already in use\n", buf);
- continue;
- }
-
- /* Save output handler and temporarily redirect output to null */
- rawsave = ifp->raw;
- ifp->raw = bitbucket;
- saved = 1;
-
- /* Suspend the packet input driver. Note that the transmit driver
- * is left running since we use it to send buffers to the line.
- */
- suspend (ifp->rxproc);
- #ifdef POLLEDKISS
- suspend (ap->poller);
- #endif
- break;
- }
-
- if (prompting_read ("Wink DTR? ", s, buf, sizeof(buf)) < 0)
- goto quit;
- if (buf[0] == 'y' || buf[0] == 'Y') {
- (void) asy_ioctl (ifp, PARAM_DTR, 1, 0); /* drop DTR */
- (void) kpause (1000L);
- (void) asy_ioctl (ifp, PARAM_DTR, 1, 1); /* raise DTR */
- }
-
- if (prompting_read ("Turn off local echo? ", s, buf, sizeof(buf)) < 0)
- goto quit;
- if (buf[0] == 'y' || buf[0] == 'Y')
- tprintf ("%c%c%c%c%c%c", IAC, WILL, TN_ECHO, IAC, WILL, TN_SUPPRESS_GA);
-
- /* Now fork into receive and transmit processes */
- rxproc = newproc ("term rx", 270, termrx, s, ifp, NULL, 0);
-
- /* We continue to handle the TCP->asy direction */
- while ((i = recvchar (s)) != EOF) {
- while (i == IAC) {
- i = recvchar (s); /* DO/DONT/WILL/WONT */
- if (i == IAC)
- break; /* escaped IAC */
- i = recvchar (s); /* opt */
- i = recvchar (s);
- }
- if (i == '\n')
- i = '\r'; /* NL => CR */
- bp = pushdown (NULLBUF, 1);
- #if 1
- bp->data[0] = (unsigned char) i;
- #else
- bp->data[0] = (i & 0x7f);
- #endif
- (void) asy_send (ifp->dev,bp);
- ifp->lastsent = secclock();
- if (i == '\r')
- kwait(NULL); /* give output buffers a chance to empty */
- }
-
- quit:
- if (saved) {
- killproc (rxproc);
- if (ifp) {
- ifp->raw = rawsave;
- resume (ifp->rxproc);
- }
- #ifdef POLLEDKISS
- if (ap)
- resume (ap->poller);
- #endif
- }
- log (s, "close term");
- Curproc->input = -1; /* avoid closing s twice */
- }
-
-
- static void
- termrx (s, p1, p2)
- int s;
- void *p1;
- void *p2 OPTIONAL;
- {
- int c;
- struct iface *ifp = (struct iface *)p1;
-
- while ((c = get_asy (ifp->dev)) != EOF) {
- #if 1
- (void) usputc (s, uchar(c));
- #else
- usputc (s, c & 0x7f);
- #endif
- usflush (s);
- }
- }
-
-
- static int
- prompting_read (prompt, s, buf, buflen)
- const char *prompt;
- int s, buflen;
- char *buf;
- {
- int nread;
-
- if (prompt) {
- (void) usputs (s, prompt);
- usflush (s);
- }
- nread = recvline (s, (unsigned char *) buf, (unsigned) buflen);
- return nread;
- }
-
-
- int
- doterm (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- int i;
- struct portlist *pl, *pnext;
-
- if (argc == 1)
- usage:
- tputs ("Usage: term ports [portlist] | term password pwstring\n");
- else if (!strcmp( argv[1], "ports")) {
- if (argc == 2) {
- tputs ("term ports: ");
- for (pl = Termports; pl; pl = pl->next)
- tprintf ("%s ", pl->portname);
- tputc ('\n');
- } else {
- for (pl = Termports; pl; pl = pnext) {
- free (pl->portname);
- pnext = pl->next;
- free (pl);
- }
- Termports = NULLPL;
- for (i = 2; i < argc; i++) {
- pl = mallocw (sizeof (struct portlist));
- pl->portname = strdup (argv[i]);
- pl->next = Termports;
- Termports = pl;
- }
- }
- } else if (!strncmp (argv[1], "pass", 4)) {
- if (argc != 3)
- goto usage;
- free (Termpass);
- Termpass = strdup (argv[2]);
- } else
- goto usage;
- return 0;
- }
-
- #endif /* TERMSERVER */
-